import { Component, Input, EventEmitter, Output, ViewChild } from "@angular/core";
import { ColumnOptions } from "../../../../shared/components/table/models/columnOptions.model";
import { PaginationPositionDisplayEnum, TableComponent } from "../../../../shared/components/table/table.component";
import { TableOptions } from "../../../../shared/components/table/models/tableOptions.model";
import { ReportingService, TargetType } from "../../reporting.service";
import { CriteriaResultModel, CriteriaModel } from "../../models/criteriaResult.model";
import { FilterModel } from "../../models/filter.model";
import { TableRouterLink } from "../../../../shared/components/table/models/tableRouterLink.model";
import { ColumnButton } from "../../../../shared/components/table/models/columnButton.model";
import { ModalComponent } from "../../../../shared/components/modal/modal.component";

@Component({
    selector: 'results-output',
    templateUrl: 'results.component.html',
    styleUrls: ['../../reporting.component.scss']
})
export class ResultsComponent {
    public filterValidity: any = {
        isValidEnabled: true,
        isNotValidEnabled: true,
        isNAEnabled: true
    };
    public result: CriteriaResultModel;
    public source: any[] = [];
    public elementCount: number = 0;
    public itemsPerPage: number = 5;
    public paginationPosition: PaginationPositionDisplayEnum = PaginationPositionDisplayEnum.Down;
    public columns: ColumnOptions[] = [
        new ColumnOptions('CompanyNameLowerCase', 'companyName', 'Company Name/ID', 'col-md-4', false, true, false, undefined, false, true, false, true)
    ];

    @Input() filter: FilterModel;

    @Input() set securities(value: boolean) {
        if (value == true) {
            this.columns[0].sizeClass = "col-md-4"; //company name
            this.addSecurityColumns();
        }
        else if (value == false) {
            let securityIndex = this.columns.findIndex(x => x.sortIdentifier == 'securityIdentifier');
            if (securityIndex > -1)
                this.columns.splice(securityIndex, 2);
            
            
            this.columns[0].sizeClass = this.filter.targetType == TargetType.Report ? "col-md-12" : "col-md-6"; //company name. For reporting, we do not have isValid column
            if(this.columns.length > 1 && this.columns[1].sortIdentifier == 'isValid')
                this.columns[1].sizeClass = "col-md-6"; //result            
        }

        this.results.setCols(this.columns);
    }

    @Input() set screening(value: boolean) {
        if (value == true) {
            this.columns.push(new ColumnOptions('isValid', 'isValid', 'Result', 
                this.columns.findIndex(x => x.sortIdentifier == 'securityIdentifier') > -1 ? 'col-md-3' : 'col-md-6', false, false, false, undefined, false, false, false, true,
                [
                    new ColumnButton('available', 'available_disabled', 'Meets filter criteria', 1, (value: boolean) => {
                        this.startLoading.emit();
                        this.filterValidity.isValidEnabled = value;
                        this.getBulkResults(new TableOptions('CompanyNameLowerCase', this.itemsPerPage), this.getValidity());
                    }),
                    new ColumnButton('notAvailable', 'notAvailable_disabled', 'Does not meet filter criteria', 0, (value: boolean) => {
                        this.startLoading.emit();
                        this.filterValidity.isNotValidEnabled = value;
                        this.getBulkResults(new TableOptions('CompanyNameLowerCase', this.itemsPerPage), this.getValidity());
                    }),
                    new ColumnButton('noData', 'noData_disabled', 'No data', -1, (value: boolean) => {
                        this.startLoading.emit();
                        this.filterValidity.isNAEnabled = value;
                        this.getBulkResults(new TableOptions('CompanyNameLowerCase', this.itemsPerPage), this.getValidity());
                    })
                ]));
        }
    }

    @Input() hasCriteria: boolean;

    @Output() finishedLoading: EventEmitter<any> = new EventEmitter();

    @Output() startLoading: EventEmitter<void> = new EventEmitter<void>();

    @ViewChild('results') results: TableComponent;

    @ViewChild('reorderModal') reorderModal: ModalComponent;

    constructor(private toolsService: ReportingService) { }    

    public tableOptionsChanged(tableOptions: TableOptions): void {
        this.startLoading.emit();
        this.getBulkResults(tableOptions);
    }

    public getBulkResults(tableOptions: TableOptions, isValid: number = undefined) {
        //when do we use settings?   
        this.toolsService.getResults(
            this.filter.id,
            !tableOptions.pageOptions.listOnly,
            tableOptions.orderByAsc,
            tableOptions.orderByCol,
            tableOptions.pageOptions.skip,
            tableOptions.pageOptions.take,
            isValid,
            this.filter.portfolioId
        ).subscribe(data => {
            //update criteria info (companiesCount)
            this.result = data;
            if (!tableOptions.pageOptions.listOnly)
                this.elementCount = data.count == 0 || (data.count == 1 && data.items[0].companyName == null) ? 0 : data.count;

            //map input companies to a simpler structure for the table to display, where criteria values are cell values
            let ret: any[] = [];
            data.items.forEach(company => {
                let columnData: any = {};
                this.columns.forEach(column => {
                    if (column.fixedColumn == true)
                        if (column.hasRouterLink)
                            columnData[column.sortIdentifier] = new TableRouterLink(company.companyName, true, company.companyNameUrlFriendly, 'overview', false, company.capitalIqid);
                        else
                            columnData[column.sortIdentifier] = company[column.sortIdentifier];
                    else {
                        //columns not fixed correspond to selected criteria
                        company.criteria.forEach(criteria => {
                            columnData[criteria.filterCriteriaId] = this.getCriteriaValue(criteria);
                        });
                    }
                });
                ret.push(columnData);
            });
            this.source = ret;
            this.finishedLoading.emit({ count: data.items.length, criteria: data.items[0].criteria });
        });
    }

    public displayResults() {
        this.startLoading.emit();
        this.toolsService.generateFilterResults(this.filter.id, this.filter.portfolioId, this.filter.universeId, this.filter.targetType == TargetType.Report, false).subscribe(_ => {
            this.getBulkResults(new TableOptions('CompanyNameLowerCase', this.itemsPerPage));
        })
    }

    public clearResults() {
        this.elementCount = 0;
        this.result = undefined;
        this.source = [];
    }

    public setCriteriaColumns(criteria: CriteriaModel[]) {
        this.clearResults();
        //clear columns array of elements that are not fixed
        let newCols = this.columns.filter(x => x.fixedColumn == true);
        //append new array of columns from the selectedCriteria array
        criteria.forEach(element => {
            newCols.push(new ColumnOptions(element.filterCriteriaId, element.filterCriteriaId, element.name, 'col-md-2', false, false, false, undefined, false, false, false, false, undefined, false, false, true));
        });
        this.columns = newCols;
    }

    private getValidity(): number {
        let ret: number = null;
        if (this.filterValidity.isValidEnabled) {
            ret = 1;
            if (this.filterValidity.isNotValidEnabled) {
                if (!this.filterValidity.isNAEnabled)
                    ret = 4;
                else
                    ret = null;
            }
            else if (this.filterValidity.isNAEnabled)
                ret = 2;
        }
        else if (this.filterValidity.isNotValidEnabled) {
            ret = 0;
            if (this.filterValidity.isNAEnabled)
                ret = 3;
        }
        else
            ret = -1

        return ret;
    }

    private getCriteriaValue(criteria: any): string {
        let ret: string;
        if (criteria.valueType == 0)
            ret = (criteria.stringValue == null || typeof (criteria.stringValue) === 'undefined') ? 'No data' : criteria.stringValue;
        else
            ret = (criteria.numericValue == null || typeof (criteria.numericValue) === 'undefined') ? 'No data' : criteria.numericValue;

        return ret;
    }

    private addSecurityColumns() {
        let securityIndex = this.columns.findIndex(x => x.sortIdentifier == 'securityIdentifier');
        if (securityIndex == -1)
            this.columns.splice(1, 0,
                new ColumnOptions('securityIdentifier', 'securityIdentifier', 'Security Name', 'col-md-3', false, false, false, undefined, false, false, false, true, undefined, false, false, true),
                new ColumnOptions('securityId', 'securityId', 'Security ID', 'col-md-3', false, false, false, undefined, false, false, false, true, undefined, false, false, true));
    }
}